import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Checkbox, Menu, message } from 'antd';
import styles from './index.less';

const { SubMenu } = Menu;

class MultiSelectableTreeMenus extends Component {

  static defaultProps = {
    mode: 'inline'
  };

  constructor(props) {
    super(props);
    this.state = {
      menuList: this.buildMenuKeys(props.menuList),
      selectedList:[]
    }
    this.menuKeyMap = {};
  }

  handleCheckboxChange = (e) => {
    let { selectedList } = this.state;
    const key = e.target.value;
    if(e.target.checked) {
      selectedList.push(key);
    } else {
      let { parent } = this.menuKeyMap[key];
      const keys = [key];
      while(parent) {
        keys.push(parent.key);
        parent = parent.parent;
      }
      selectedList = selectedList.filter(x=>!keys.includes(x));
    }
    selectedList = [...new Set(selectedList)];
    this.setState({ selectedList }, ()=>this.props.onSelectedMenuChange(selectedList));
  }

  handleCheckboxAllChange = (e) => {
    let { keys } = this.menuKeyMap[e.target.value];
    let { selectedList } = this.state;
    if(e.target.checked) {
      selectedList = [...selectedList, ...keys];
    } else {
      const key = e.target.value;
      let { parent } = this.menuKeyMap[key];
      while(parent) {
        keys = [...keys, parent.key];
        parent = parent.parent;
      }
      selectedList = selectedList.filter(x=>!new Set(keys).has(x));
    }
    selectedList = [...new Set(selectedList)];
    this.setState({ selectedList }, ()=>this.props.onSelectedMenuChange(selectedList));
  }


  getMenuKeys = (menu) => {
    const keys = [menu.key];
    if(menu.children) {
      menu.children.forEach(child=>{
        keys.push(...this.getMenuKeys(child));
      })
    }
    return keys;
  }

  buildMenuKeys = (menuList) => {
    if(!menuList) {
      message.error('查询菜单不能为空');
      return [];
    }
    return menuList.map(menu=>{
      if(!menu.children) {
        return {
          ...menu,
          keys: this.getMenuKeys(menu),
        }
      } else {
        return {
          ...menu,
          keys: this.getMenuKeys(menu),
          selected: [],
          children: this.buildMenuKeys(menu.children)
        }
      }
    });
  }

  includes = (a, b) => {
    const t = [];
    b.forEach(i=>{
      if(a.includes(i)) {
        t.push(i);
      }
    });
    return t.length===b.length?true:false;
  }

  includesAllChildren = (key) => {
    const { selectedList } = this.state;
    const { keys } = this.menuKeyMap[key];
    if(this.includes([...selectedList, key], keys)) {
      this.setState({ selectedList:[...new Set([...selectedList, key])] });
      return true;
    }
    return false;
  }

  buildMenuNodes = (menuList) => {
    if(!menuList) {
      message.error('查询菜单节点不能为空');
      return [];
    }
    return menuList.map(item => {
      this.menuKeyMap[item.key] = item;
      if (!item.children) {
        return (
          <Menu.Item key={item.key}>
            <Checkbox className={styles.spaceRight2} onClick={e=>e.stopPropagation()} onChange={this.handleCheckboxChange} value={item.key}
                      checked={this.state.selectedList.includes(item.key)}>{item.title}</Checkbox>
          </Menu.Item>
        )
      } else {
        return (
          <SubMenu
            key={item.key}
            title={
              <>
                <Checkbox className={styles.spaceRight2} onClick={e=>e.stopPropagation()} onChange={this.handleCheckboxAllChange} value={item.key}
                          checked={this.state.selectedList.includes(item.key)||this.includesAllChildren(item.key)}></Checkbox>
                <span>{item.title}</span>
              </>
            }
          >
            {this.buildMenuNodes(item.children)}
          </SubMenu>
        )
      }
    });
  };

  componentWillReceiveProps(nextProps) {
    if(nextProps.menuList !== this.props.menuList) {
      this.setState({
        menuList: this.buildMenuKeys(nextProps.menuList),
        selectedList:[]
      });
    }
  }

  render() {
    const { defaultSelectedKeys, defaultOpenKeys, mode } = this.props;
    return (
      <Menu
        mode={mode.toLowerCase()}
        defaultSelectedKeys={defaultSelectedKeys}
        defaultOpenKeys={defaultOpenKeys}
        selectable = {false}
      >{
        this.buildMenuNodes(this.state.menuList)
      }
      </Menu>
    );
  }
}

MultiSelectableTreeMenus.propTypes = {
  menuList: PropTypes.object.isRequired,
  defaultSelectedKeys: PropTypes.array,
  defaultOpenKeys: PropTypes.array,
  mode: PropTypes.string,
  onSelectedMenuChange: PropTypes.func.isRequired
};

export default MultiSelectableTreeMenus;
